#ifndef EXPR_H
#define EXPR_H

#include "tree.h"
#include <string>


class OpCodeGen;
class VarSymbol;
class FunctionSymbol;
class ConstantSymbol;
class FunctionDefStatement;

class Expr : public Tree{
public:
    Expr();
    ~Expr();
    void accept(Visitor* v);
};

class VariableExpr : public Expr{
public:
    /// the literal name
    std::string *name;

    /// the line number of definition
    int defLine;

    VarSymbol   *varSym;
    VariableExpr(const char *var);
    ~VariableExpr();
    void accept(Visitor* v);
};

class FunctionNameExpr : public VariableExpr{
public:
    FunctionNameExpr(const char *var);
    ~FunctionNameExpr();

    FunctionSymbol  *funcSym;
    void accept(Visitor *v);
};


class ConstantExpr : public Expr{
public:
    typedef int  const_expr_type;
    static const const_expr_type    CONST_INTEGER = 0;
    static const const_expr_type    CONST_DOUBLE = CONST_INTEGER + 1;
    static const const_expr_type    CONST_STRING = CONST_DOUBLE + 1;

    std::string *value;
    const_expr_type type;
    ConstantSymbol  *constSym;
    ConstantExpr(const char* str,const_expr_type t);
    ~ConstantExpr(){};


    void accept(Visitor* v);
};

class BinaryExpr : public Expr{
public:
    Tree *left,*right;
    BinaryExpr(Tree *l,Tree *r):left(l),right(r){};
    ~BinaryExpr(){};
    void    accept(Visitor* v);
    virtual int    getOperator();
};

class AddExpr : public BinaryExpr{
public:
    AddExpr(Tree *l,Tree *r);
    int    getOperator();
};

class MinusExpr : public BinaryExpr{
public:
    MinusExpr(Tree *l,Tree *r);
    int    getOperator();
};

class MulExpr : public BinaryExpr{
public:
    MulExpr(Tree *l,Tree *r);
    int    getOperator();
};

class DivExpr : public BinaryExpr{
public:
    DivExpr(Tree *l,Tree *r);
    int    getOperator();
};


#endif // EXPR_H


